<?php
/**
 * Created by PhpStorm.
 * User: lihui
 * Date: 3/26/2021
 * Time: 16:36
 */
namespace app\common\model\coin;

use app\common\model\base\A3Mall;
use app\common\model\Calculation;
use app\common\model\file\Association;
use app\common\model\order\OrderTake;

use app\common\traits\recordAllRun;
use mall\basic\Users;
use think\facade\Db;

class CoinRuleRun extends A3Mall
{

    use recordAllRun;   //使用链表查询处理

    protected $autoWriteTimestamp = true;
    protected $name = "coin_rule_run";

    protected $type = [
        "id"=>"string",
        "unique_id"=>"integer",
        "coin_rule_id"=>"integer",
        "cover_times"=>"integer",
        "cover_times_auto"=>"integer",
        "cover_times_manual"=>"integer",
        "amount"=>"string",
        "quantity"=>"string",
        "unit_price"=>"string",
        "version"=>"integer",
        "create_time"=>"integer",
        "update_time"=>"integer",
    ];

    const STATUS_OPEN = 1;    //开启
    const STATUS_CLOSE = 2; // 关闭

    //状态类型
    private static $status_text_mapping=[
        self::STATUS_OPEN=>'开启',
        self::STATUS_CLOSE=>'关闭'
    ];


    // 小数点位数
    public $scale = 20;


    /** 获取关联所有数据的列表
     * @param array $whereTmp  条件
     * @param array $limit  查询数量
     * @param string $order 排序
     * @param array $fields 查询字段（暂缺）
     * @return array
     */
    public function recordAll($whereTmp = [],$limit = [],$orderTmp = [],$fieldsTmp= []) {

        return $this->recordAllRun([$whereTmp,$limit,$orderTmp,$fieldsTmp],[],[
        ]);
    }


    /**
     *  创建默认数据
     * @param int $coinRuleId   策略ID
     * @param array $lastRunDetails 策略上次执行结果集合数据
     * @return array
     * @throws \Exception
     * @data 2021-04-09
     */
    public function recordCreateDefault(int $coinRuleId,$lastRunDetails = []) {
        $insertData = [
            'unique_id' => $coinRuleId,
            'coin_rule_id' => $coinRuleId,
            'cover_times' => 0,
            'cover_times_auto' => 0,
            'cover_times_manual' => 0,
            'amount' => 0,
            'quantity' => 0,
            'unit_price' => 0,

            'last_id'   => $lastRunDetails['id']?$lastRunDetails['id']:0,
            'last_remaining_quantity'   => $this->getRemainingQuantity($lastRunDetails),
            'deviations_quantity'   => 0,
            'reserved_quantity' => 0,
            'reserved_price'    => 0,

            'version' => 1,
            'create_time' => time(),
            'update_time' => time(),
        ];
        $insertData['id'] = $this->insertGetId($insertData);
        // 更新规则中的ID
        (new CoinRule())->updateRunId($coinRuleId,$insertData['id']);
        return $insertData;
    }


    /**
     * 计算上次执行剩余数量
     * @param $details 上次执行中数据
     * @return int|string 返回对应数量
     */
    public function getRemainingQuantity($details){
        $quantity = 0;
        if(!$details['id']) {
            return $quantity;
        }
      /*  $quantity = bcadd($details['quantity'],$details['last_remaining_quantity'],$this->scale);
        $quantity = bcadd($quantity,$details['deviations_quantity'],$this->scale);
        $quantity = bcsub($quantity,$details['reserved_quantity'],$this->scale);
        $quantity = bcsub($quantity,$details['sell_quantity'],$this->scale);*/
        return self::trimZero($details['remaining_quantity']);
    }



    /**
     * 关闭监控状态
     * @param $runId 执行中的ID
     * @param $ruleId   规则ID
     * @param $updateExtData 额外的更新字段
     * @param $version  执行中当前版本号
     */
    public function closeMonitor($runId,$ruleId,$version,array $updateExtData = null) {
        $coinRuleClass = new CoinRule();
        if(!$details = $coinRuleClass->recordAll([
            'id'    => $ruleId,
            'coin_rule_run_id'  => $runId,
            'coin_rule_run-version' => $version,
        ],1,[],[''])) {
            return false;
        }
        // 更新策略组数据，是否重复
        $coinRuleClass->updateRunId($ruleId,0,$details['type'] == $coinRuleClass::TYPE_ONE?null:$coinRuleClass::STATUS_CLOSE,$runId);

        if(!$this->recordUpdate([
            'id'    => $runId,
            'version'   => $version,
        ],array_merge([
            'unique_id' => $ruleId . '_' . $runId,
        ],empty($updateExtData)?[]:$updateExtData))) {
            return false;
        }
        return true;
    }



    /**
     * 编辑记录
     * @param array $where 条件
     * @param array $updateData 数据
     */
    public function recordUpdate(array $where,array $updateData) {
        $updateData = array_merge($updateData,[
            'update_time'   => time(),
            'version'   => Db::raw('if(version>65000,1,version+1)'),
        ]);

        // 更新数据
        return $this->where($where)->update($updateData);
    }



    /**
     * 获取详情
     * @param $id
     * @return array|null|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function findById($id,$userId = null) {
        $where = [
            'id'    => $id,
        ];
        if(!empty($userId)) {
            $where['publisher_id'] = $userId;
        }
        return $this->where($where)->find();
    }

    /**
     * 关联需求详情
     */
    public function coin() {
        return $this->hasOne(Coin::class,"id","coin_id")->joinType("INNER");
    }

    /**
     * 获取发布者
     * @return \think\model\relation\HasOne
     */
    public function user() {
        return $this->hasOne(\app\common\model\users\Users::class,"id","user_id")->joinType("INNER");

    }

    /**
     * 关联获取图片详情
     * @return \think\model\relation\HasMany
     */
    public function images() {
        return $this->hasMany(Association::class,'association_id','id')
            ->where('association_type','=',Association::ASSOCIATION_TYPE_LIST[static::FILE_TYPE])->where('status','=',Association::STATUS_EFFECTIVE)
            ->field('filename');
    }

    /**
     * 获取用户ID
     * @param null $userId 用户ID
     * @return int|mixed|null
     * @throws \Exception
     */
    private function getUserId($userId = null) {
        if(!$userId = is_integer($userId)?$userId:Users::get('id')) {
            throw new \Exception('获取用户ID信息失败');
        }
        return $userId;
    }


    //获取状态文本
    public static function getStatusText(int $status){
        return self::$status_text_mapping[$status] ?? '';
    }

    //获取状态列表
    public static function getStatusList()
    {
        return self::$status_text_mapping;
    }



    public function getList($condition,$size=10,$page=1){
        $count = $this->withJoin(["coin"])->where($condition)->count();
        $data = $this->withJoin(["coin"])->where($condition)->order('job.id','DESC')->paginate($size);
        return [
            "count"=>$count,
            "data"=>array_map([$this,'format'],$data->items())
        ];
    }


    public function getStatusTextAttr($value,$data)
    {
        return static::getStatusText($data['status']) ?? '';
    }

    public function getCreateTimeAttr($value){
        return date("Y-m-d H:i:s",$value);
    }

    public function getUpdateTimeAttr($value)
    {
        return date("Y-m-d H:i:s",$value);
    }

    protected function format($value)
    {
//        $value->status_name=$value->status_text;
//        $value->type_name= $value->type_name ?? $value->job_type->name ?? $value->jobType__name;
//        $value->publisher=$value->username;
//        $value->publish_time_text=$value->publish_time_text;
//        $value->exp_time_text=$value->exp_time_text;
        return $value;
    }


    /**
     * 格式化价格
     * @param $price 价格
     * @return string|string[]|null
     */
    public static function trimZero($price,$scale = 30) {
        return Calculation::trimZero($price,$scale);
    }

}
